
import React, { Component } from 'react';
import './index.css';
import * as THREE from 'three';    //引入three基础相关的所有模块
import { Scene } from 'three';
import Stats from 'three/examples/js/libs/stats.min.js';  //引入状态监测
import TWEEN from "@tweenjs/tween.js";
import * as dat from 'dat.gui';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';  // 控制器：鼠标控制旋转
import { Lut } from 'three/examples/jsm/math/Lut.js';  // 颜色条
import { connect } from 'react-redux';


const ThreeBSP = require('three-js-csg')(THREE);
var camera, scene, renderer, scene1, orthoCamera, controlst;
var tubeMaterial1 = new THREE.ShaderMaterial({
  side: THREE.DoubleSide,    //THREE.DoubleSide:双面绘制,外面和里面
  vertexColors: true,
  // 顶点着色器
  vertexShader: ` 
    varying vec3 vNormal;
    void main() {
      //将attributes的normal通过varying赋值给了向量vNormal
        vNormal = normal;
      //projectionMatrix是投影变换矩阵 modelViewMatrix是相机坐标系的变换矩阵 
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );   
    }
  `,
  // 片元着色器
  fragmentShader: `
    //片元着色器同样需要定义varying vec3 vNormal；
    varying vec3 vNormal;
    void main() {
      //vNormal是一个已经归一化的三维向量
        float pr = (vNormal.x + 1.0) / 2.0; //pr红色通道值范围为0~1
        float pg = (vNormal.y + 1.0) / 2.0; //pg绿色通道值范围为0~1
        float pb = (vNormal.z + 1.0) / 2.0; //pb蓝色通道值范围为0~1
      //最后设置顶点颜色，点与点之间会自动插值
        gl_FragColor=vec4(pr, pg, pb, 1.0); 
    }
  `
});
var tubeMaterial2 = new THREE.ShaderMaterial({
  side: THREE.DoubleSide,    //THREE.DoubleSide:双面绘制,外面和里面
  vertexColors: true,
  // 顶点着色器
  vertexShader: ` 
    varying vec3 vNormal;
    void main() {
      //将attributes的normal通过varying赋值给了向量vNormal
        vNormal = normal;
      //projectionMatrix是投影变换矩阵 modelViewMatrix是相机坐标系的变换矩阵 
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );   
    }
  `,
  // 片元着色器
  fragmentShader: `
    //片元着色器同样需要定义varying vec3 vNormal；
    varying vec3 vNormal;
    void main() {
      //vNormal是一个已经归一化的三维向量
        float pr = (vNormal.x + 1.0) / 2.0; //pr红色通道值范围为0~1
        float pg = (vNormal.y + 1.0) / 2.0; //pg绿色通道值范围为0~1
        float pb = (vNormal.z + 1.0) / 2.0; //pb蓝色通道值范围为0~1
      //最后设置顶点颜色，点与点之间会自动插值
        gl_FragColor=vec4(pr, pg, pb, 1.0); 
    }
  `
});
var tubeMaterial3 = new THREE.ShaderMaterial({
  side: THREE.DoubleSide,    //THREE.DoubleSide:双面绘制,外面和里面
  vertexColors: true,
  // 顶点着色器
  vertexShader: ` 
    varying vec3 vNormal;
    void main() {
      //将attributes的normal通过varying赋值给了向量vNormal
        vNormal = normal;
      //projectionMatrix是投影变换矩阵 modelViewMatrix是相机坐标系的变换矩阵 
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );   
    }
  `,
  // 片元着色器
  fragmentShader: `
    //片元着色器同样需要定义varying vec3 vNormal；
    varying vec3 vNormal;
    void main() {
      //vNormal是一个已经归一化的三维向量
        float pr = (vNormal.x + 1.0) / 2.0; //pr红色通道值范围为0~1
        float pg = (vNormal.y + 1.0) / 2.0; //pg绿色通道值范围为0~1
        float pb = (vNormal.z + 1.0) / 2.0; //pb蓝色通道值范围为0~1
      //最后设置顶点颜色，点与点之间会自动插值
        gl_FragColor=vec4(pr, pg, pb, 1.0); 
    }
  `
});
var tubeMaterial4 = new THREE.ShaderMaterial({
  side: THREE.DoubleSide,    //THREE.DoubleSide:双面绘制,外面和里面
  vertexColors: true,
  // 顶点着色器
  vertexShader: ` 
    varying vec3 vNormal;
    void main() {
      //将attributes的normal通过varying赋值给了向量vNormal
        vNormal = normal;
      //projectionMatrix是投影变换矩阵 modelViewMatrix是相机坐标系的变换矩阵 
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );   
    }
  `,
  // 片元着色器
  fragmentShader: `
    //片元着色器同样需要定义varying vec3 vNormal；
    varying vec3 vNormal;
    void main() {
      //vNormal是一个已经归一化的三维向量
        float pr = (vNormal.x + 1.0) / 2.0; //pr红色通道值范围为0~1
        float pg = (vNormal.y + 1.0) / 2.0; //pg绿色通道值范围为0~1
        float pb = (vNormal.z + 1.0) / 2.0; //pb蓝色通道值范围为0~1
      //最后设置顶点颜色，点与点之间会自动插值
        gl_FragColor=vec4(pr, pg, pb, 1.0); 
    }
  `
});
var tubeMaterial5 = new THREE.ShaderMaterial({
  side: THREE.DoubleSide,    //THREE.DoubleSide:双面绘制,外面和里面
  vertexColors: true,
  // 顶点着色器
  vertexShader: ` 
  varying vec3 vNormal;
  void main() {
    //将attributes的normal通过varying赋值给了向量vNormal
      vNormal = normal;
    //projectionMatrix是投影变换矩阵 modelViewMatrix是相机坐标系的变换矩阵 
      gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );   
  }
`,
  // 片元着色器
  fragmentShader: `
  //片元着色器同样需要定义varying vec3 vNormal；
  varying vec3 vNormal;
  void main() {
    //vNormal是一个已经归一化的三维向量
      float pr = (vNormal.x + 1.0) / 2.0; //pr红色通道值范围为0~1
      float pg = (vNormal.y + 1.0) / 2.0; //pg绿色通道值范围为0~1
      float pb = (vNormal.z + 1.0) / 2.0; //pb蓝色通道值范围为0~1
    //最后设置顶点颜色，点与点之间会自动插值
      gl_FragColor=vec4(pr, pg, pb, 1.0); 
  }
`
});
var gridHelper = new THREE.GridHelper(500, 50, 0xffffff, 0x555555);  // 网格宽度(默认10),等分数(10)，中心线颜色(0x444444)，网格线颜色(0x888888)
gridHelper.rotateOnAxis(new THREE.Vector3(1, 0, 0), 90 * (Math.PI / 180));
gridHelper.position.set(0, -30, 20)
var geometry = new THREE.Geometry();
var material = new THREE.LineBasicMaterial({ color: 0xff9800, linewidth: 4, linejoin: 'round' });
class ThreeShowDemo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      zData: [],  // x轴数据（红），深度
      yData: [],   // y轴数据（绿），左右偏差
      xData: [],   // z轴数据（蓝），上下偏差
      curve: []
    };

    this.handleAddCurve = this.handleAddCurve.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    console.log(nextProps)
    // console.log(this.props)
    // console.log(nextProps.selectedCurve)
    if (nextProps.selectedCurve !== this.props.selectedCurve) {
      this.handleAddCurve();
      this.initThree();
    } else {
      if (nextProps.docData.yData.length === this.props.docData.yData.length) {
        this.handleAddCurve();
        this.initThree();
      }
    }

  }
  componentWillMount() {
    const docData = this.props.docData;
    if (docData.doc_type === '纯数据文件') {
      this.setState({
        zData: docData.yData
      })
      docData.curves.map((item) => {
        if (item.curve_name === '上下偏差') {
          this.setState({
            xData: item.xData
          })
        }
        else if (item.curve_name === '左右偏差') {
          this.setState({
            yData: item.xData
          })
        } else if (item.curve_name === '伽马') {//设置被选曲线初始值为伽马
          this.setState({
            curve: item.xData
          })
        }
      })
    }
    //   else if(docData.doc_type === '绘图文件'){
    //     docData.docData.curves.map((item)=>{
    //       docData.curves.map((item)=>{
    //         if(item.curve_name==='上下偏差'){
    //           console.log('dddsddd1');
    //           console.log(item.xData);
    //            this.setState({
    //             zData:item.xData
    //            })
    //          }
    //         else if(item.curve_name==='左右偏差'){
    //           console.log('dddsddd2');
    //           console.log(item.xData);
    //             this.setState({
    //             xData:item.xData
    //             })
    //         }
    //       })
    //     })
    //  }
  }
  handleAddCurve = () => {//获取曲线数据以对井轨着色
    const curve_id = this.props.threeDimData.selectedCurve;
    // console.log('hhhhhhhhhh1', curve_id);
    const docData = this.props.docData;
    // console.log('hhhhhhhhhh2', docData);
    if (docData.doc_type === '纯数据文件') {
      // this.setState({
      //   zData: docData.yData
      // })
      this.state.zData = docData.yData;
      docData.curves.map((item) => {
        if (item.curve_name === '上下偏差') {
          // this.setState({
          //   xData: item.xData
          // })
          this.state.xData = item.xData
        }
        else if (item.curve_name === '左右偏差') {
          // this.setState({
          //   yData: item.xData
          // })
          this.state.yData = item.xData
        } else if (item.curve_name === '伽马') {//设置被选曲线初始值为伽马
          // this.setState({
          //   curve: item.xData
          // })
          this.state.curve = item.xData
        }
      })
    }
    //   else if(docData.doc_type === '绘图文件'){
    //     docData.docData.curves.map((item)=>{
    //       if(item.curve_id===curve_id){
    //         console.log('chenggong');
    //         this.setState({
    //           curve:item.xData
    //         },console.log('curve的数据',this.state.curve))
    //       }

    //     })
    //  }
  }

  initThree = () => {   // 初始化，准备数据  四大组件：场景、相机、渲染器、几何体
    // var xcurveData=[500,50,-150,-250,-350,-750], 
    // ycurveData=[300,20,-120,-220,-320,-720], 
    // zcurveData=[500,300,280,270,260,250];//接收到的井轨的三位坐标
    var xcurveData = this.state.xData,
      ycurveData = this.state.yData,
      zcurveData = this.state.zData,//接收到的井轨的三位坐标
      curveData = this.state.curve;//接受到的选中的曲线数据
    console.log(curveData)
    // console.log('所选曲线数据', curveData);
    //对曲线数据进行归一化操作
    let min = Math.max(...curveData);
    let max = Math.min(...curveData);
    let newCurveData = curveData.map(item => ((item - min) / (max - min)).toFixed(2));
    // console.log('endendhaha', newCurveData);
    this.clearScene();
    threeStart();

    function initScene() {    // 1、初始化 场景sence
      scene = new THREE.Scene();
      scene1 = new THREE.Scene();
    }

    function initCamera() {   // 2、初始化 相机camera  
      //（透视相机） PerspectiveCamera( fov, aspect, near, far ): 视角的度数，显示范围的宽高比，最近的距离，最远看到的距离
      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);

      // 设置相机 的位置(position/up/lookat 三个方向确定了相机的唯一位置方向)：？？？？？？？？？？？？？？
      camera.position.set(150, 30, 80)   // 400,400,400
      camera.up.set(0, 0, 1);  // 垂直于快门的一条线（相机上面）   (up与lookat两个方向一定是垂直的90度!!!!)
      camera.lookAt(0, 0, 0);  // 代表一个方向，而不是一个点，(垂直于镜头的一条线)

      orthoCamera = new THREE.OrthographicCamera(- 1, 1, 1, - 1, 1, 2);
      orthoCamera.position.set(0.5, 0, 1);
    }

    var width, height;
    function initRender() {   // 3、初始化 渲染器render
      width = document.getElementById('canvas-frame').clientWidth;
      height = document.getElementById('canvas-frame').clientHeight;
      renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });   // 如果数据量非常大，设置为false为提高性能
      renderer.setSize(width, height);   // 设置 渲染器的大小（页面大小）
      document.getElementById('canvas-frame').appendChild(renderer.domElement);  // 将渲染器渲染的内容添加到窗口上（固定写法）
      renderer.setClearColor(0x999999, 1.0);  // 设置渲染器颜色（清除时）

      renderer.autoClear = false;   //定义渲染器是否在渲染每一帧之前自动清除其输出。
      renderer.setPixelRatio(window.devicePixelRatio);   //设置设备像素比。避免设备上绘图模糊
    }

    var tubeGeometry, tubeMaterial, tubeMesh, uniforms;
    function initObject() {
      // 4、可定义多个几何体，页面上显示的物体 都定义在此  
      // 2、定义一个坐标系
      // var axisHelper = new THREE.AxisHelper(600);  // 添加一个坐标系，长度为400
      // scene.add(axisHelper);

      // 3、定义一个网格辅助线

      scene.add(gridHelper);

      for (let i = 0; i < xcurveData.length - 1; i++) {
        //4.定义一条弧线
        let points = [];
        points.push(new THREE.Vector3(xcurveData[i], ycurveData[i], zcurveData[i]));
        points.push(new THREE.Vector3(xcurveData[i + 1], ycurveData[i + 1], zcurveData[i + 1]));
        let curve = new THREE.CatmullRomCurve3(points);
        //THREE.SplineCurve3().getPoints(divisions)：该方法返回一个Vector3数组，把曲线分为divisions段，返回每个点的坐标数组。上面的例子就是通过getPoint(50)返回曲线上,50等分点的坐标，然后通过这些坐标构建一条曲线。
        geometry.vertices = curve.getPoints(500);
        var line = new THREE.Line(geometry, material);
        scene.add(line);
        //5.沿着一条曲线拉伸出一条管
        tubeGeometry = new THREE.TubeGeometry(curve, 20, 4, 30, false);  // (path:指定管的路径(SplineCurve3对象) ,segments:构成管的分段数(这里应该写深度，一个深度为一段) ,radius:管的半径 ,radiusSegments:管沿圆周方向的分段 ,closed:管两端是否闭合 )
        //6.根据归一化后所选曲线的值的大小判断该段应选材质，标定不同区间不同颜色
        if (newCurveData[i] >= 0 && newCurveData[i] < 0.2) {
          tubeMesh = new THREE.Mesh(tubeGeometry, tubeMaterial1);
          scene.add(tubeMesh);

        } else if (newCurveData[i] >= 0.2 && newCurveData[i] < 0.4) {

          tubeMesh = new THREE.Mesh(tubeGeometry, tubeMaterial2);
          scene.add(tubeMesh);

        } else if (newCurveData[i] >= 0.4 && newCurveData[i] < 0.6) {

          tubeMesh = new THREE.Mesh(tubeGeometry, tubeMaterial3);
          scene.add(tubeMesh);

        } else if (newCurveData[i] >= 0.6 && newCurveData[i] < 0.8) {

          tubeMesh = new THREE.Mesh(tubeGeometry, tubeMaterial4);
          scene.add(tubeMesh);

        } else {

          tubeMesh = new THREE.Mesh(tubeGeometry, tubeMaterial5);
          scene.add(tubeMesh);

        }

      }
    }

    function initLight() {  // 初始化 灯光
      var light1 = new THREE.AmbientLight(0x999999);
      light1.position.set(0, 0, 0);
      scene.add(light1);

      const pointLight = new THREE.PointLight(0xffffff, 1);
      camera.add(pointLight);
    }

    function initTween() {  // 初始化tween,移动 相机/物体 位置
      new TWEEN.Tween(camera.position)  // 相机位置
        .to({ x: 1000 }, 3000)     // 3秒内将相机位置x改变为400
        .repeat(Infinity)  // 重复：一直重复
        .start();   // 开始
    }


    //辅助工具
    var helper = new THREE.AxesHelper(200);
    helper.position.set(0, -30, 20);
    scene.add(helper);

    function controls() {   //控制器
      controlst = new OrbitControls(camera, renderer.domElement);
      // controls.minDistance = 20; 
      // controls.maxDistance = 600;
      // controls.addEventListener( 'change', animation );   // 监控，改变后重新渲染
    }

    var lut, sprite;
    function updateColors() {   // 设置颜色,根据顶点数值大小进行渐变配色
      lut = new Lut();
      var map = new THREE.CanvasTexture(lut.createCanvas())
      var spriteMaterial = new THREE.SpriteMaterial({ map: map })
      sprite = new THREE.Sprite(spriteMaterial);
      sprite.scale.x = 0.035;
      sprite.scale.y = 0.5;
      sprite.position.x = -0.45;
      sprite.position.y = 0.65;
      scene1.add(sprite);

      const colors = [];
      for (let i = 0, n = tubeGeometry.vertices.length; i < n; ++i) {
        colors.push([1, 1, 1]);
      }
      //setAttribute(string name, string value)：增加一个指定名称和值的新属性，或者把一个现有的属性设定为指定的值。
      tubeGeometry.colors = new THREE.Float32BufferAttribute(colors, 3)

      let params = {
        colorMap: 'rainbow',
      };
      lut.setColorMap(params.colorMap);
      lut.setMax(2000);
      lut.setMin(0);
      const geometry = tubeMesh.geometry;
      const pressures = geometry.vertices;
      const colors1 = geometry.colors;
      //console.log("lalal",pressures,colors)

      for (let i = 0; i < pressures.length; i++) {
        const color = lut.getColor(i);
        if (color === undefined) {
          // console.log('该点没有设置颜色:', pressures[i]);
        } else {
          colors1.setXYZ(i, color.r, color.g, color.b);
        }
      }
      colors1.needsUpdate = true;
      const map1 = sprite.material.map;
      lut.updateCanvas(map.image);
      map1.needsUpdate = true;
    }

    function animation() {   //  渲染函数
      //stats.begin();   // 检测器：监测执行一次需要的相关数据
      if (renderer) {
        renderer.clear();  // 清除 颜色、深度、模板 缓存
        renderer.render(scene, camera);    // 通过场景sence和相机crame一起，用 渲染器 渲染出来

        //renderer.clearDepth();  // 清除深度缓存
        renderer.render(scene1, orthoCamera);
        requestAnimationFrame(animation);  // 当render函数空闲时，不断地调用该函数进行渲染，（可实现渲染效果）
      }
      //stats.end();
    }

    function threeStart() {
      initScene();   // 场景
      initCamera();  // 相机
      initRender();  // 渲染器
      initObject();  // 几何体
      initLight(); // 光
      animation();  // 渲染函数 
      initTween();  // 动画：移动相机位置
      controls();  //控制器：鼠标控制方向和大小
      // updateColors();   // 颜色
      // createUI();
    }
    window.addEventListener('resize', this.onWindowResize, false);
  };
  clearScene = () => {
    if (renderer) {
      renderer.renderLists.dispose();
      renderer.dispose();
      renderer.forceContextLoss();
      renderer.domElement = null;
      renderer.content = null;
      renderer = null;
    }
    if (scene) scene.clear(); scene = null
    if (scene1) scene1.clear(); scene1 = null
    if (camera) camera = null;
    if (controlst) controlst = null;
    if (orthoCamera) orthoCamera = null


    document.getElementById('canvas-frame').innerHTML = ''
    THREE.Cache.clear()
    window.removeEventListener("resize", this.onWindowResize, false);
  }
  onWindowResize = () => {   // 窗口自适应
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    if (document.getElementById('canvas-frame').clientWidth) {
      renderer.setSize(document.getElementById('canvas-frame').clientWidth, document.getElementById('canvas-frame').clientHeight);
    }
    this.render();
  }

  /**
   * 开始Three
   *
   * @memberof ThreeBim
   */
  componentDidMount() {
    // this.initThree();
  }
  componentWillUnmount() {
    this.clearScene()
  }


  render() {
    return (
      <div id='canvas-frame' style={{ backgroundColor: 'red', width: '100%', height: '100%' }}>   </div>
    );
  }
}


export default connect(
  state => ({ docData: state.docData, threeDimData: state.threeDimData }),
  {}
)(ThreeShowDemo);